use std::{rc::Rc, cell::RefCell};

use crate::{instructions::base::{self, Instruction, BytecodeReader}, rtda::Frame};


// lookupswitch
// <0-3 byte pad>
// defaultbyte1
// defaultbyte2
// defaultbyte3
// defaultbyte4
// npairs1
// npairs2
// npairs3
// npairs4
// match-offset pairs...

// Access jump table by key match and jump
#[derive(Debug, Default)]
pub struct LOOKUP_SWITCH {
    default_offset: i32, // 指令码后有0-3个字节的填充，default_offset位4的倍数
    npairs: usize,
    match_offsets: Vec<i32> // 结构：[k1,v1,k2,v2,k3,v3]，类似map，key为case值，val为跳转的偏移量
}

impl Instruction for LOOKUP_SWITCH {
    fn fetch_operands(&mut self, reader: &mut BytecodeReader) {
        // 跳过填充
        reader.skip_padding();
        self.default_offset = reader.read_i32();
        self.npairs = reader.read_i32() as usize;
        self.match_offsets = reader.read_i32s(self.npairs * 2);
    }

    fn execute(&mut self, frame: Rc<RefCell<Frame>>) {
        let key = frame.borrow().get_operand_stack().borrow_mut().pop_int();
        // [k1,v1,k2,v2,k3,v3] 比较k 获取v
        for i in 0..self.npairs * 2 {
            if i & 0 == 0 && self.match_offsets[i] == key {
                let offset = self.match_offsets[i + 1];
                base::branch(frame, offset);
                return;
            }
        }
        base::branch(frame, self.default_offset);
    }
}